package pprz.components;

import info.monitorenter.gui.chart.Chart2D;
import info.monitorenter.gui.chart.ITrace2D;
import info.monitorenter.gui.chart.layout.LayoutFactory;
import info.monitorenter.gui.chart.traces.Trace2DLtd;
import info.monitorenter.gui.chart.layout.ChartPanel;

import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashMap;
import java.util.HashSet;

import javax.swing.BoxLayout;
import javax.swing.JFrame;

import net.jscience.math.MathFP;
import pprz.data_components.Message;
import pprz.data_components.events.DownlinkMessageEvent;
import pprz.data_components.events.DownlinkMessageEventListener;
import pprz.data_components.parsers.MessageParser;
import pprz.data_components.parsers.MessageParser.MessageFormat;

public class Plot extends JFrame
implements DownlinkMessageEventListener {
	
	protected static final long serialVersionUID = 1L;
	
	public static int buffSize=200; // each trace holds up tp 200 points
	protected HashSet<Long> msgSet; // msg ids
	protected Chart2D chart;
	protected HashMap<Long,ITrace2D> traces;
	HashMap<Long,MessageFormat> formats;
	
	public Plot()
	{
		allocate();
		initialize();
	}
	
	protected void allocate()
	{
		msgSet= new HashSet<Long> ();
		chart= new Chart2D();
		traces=new HashMap<Long,ITrace2D>();
	}
	
	protected void initialize()
	{
		chart.setToolTipCoords(true);
		chart.setGridColor(Color.gray);
		chart.setBackground(Color.white);
		chart.setForeground(Color.black);
		
		this.getContentPane().setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
		LayoutFactory.getInstance().createPopupMenu(chart, false);
		ChartPanel chartpanel = new ChartPanel(chart);
		this.getContentPane().add(chartpanel);
		this.getContentPane().addPropertyChangeListener(chartpanel);
		//this.getContentPane().add(new ControlPanel());
		
		
		
		
		
//		ChartPanel cp=new ChartPanel(chart);
//		LayoutFactory.getInstance().createPopupMenu(chart, true);
		
		
		
//		this.setLayout(new FlowLayout());
//		this.add(cp);
//		this.getContentPane().add(chart);
		this.addWindowListener
	       (new WindowAdapter() {
	           public void windowClosing(WindowEvent e) {
	              e.getWindow().dispose();
	              }
	           }
	       );
//		ChartPanel cp=new ChartPanel(chart);
//		this.add(cp);
		this.setSize(400,200);
	}
	
	public void setFormats(HashMap<Long,MessageParser.MessageFormat> messageFormats)
	{
		formats=messageFormats;
	}
	
	public void add(int ac, int msgid, int fldid)
	{
		
		if (formats==null) return;
		Long key=new Long((((long)ac&0xFFl)<<16<<16)+(((long)msgid&0xFFl)<<16)+(((long)fldid&0xFFl)));
		System.out.printf("adding:%d:key:%h\n",msgid,key);
		msgSet.add(key);
		
		MessageFormat format=formats.get(0*0x100000000l+msgid);
		if (format==null) return;
		
		ITrace2D trace=new Trace2DLtd(buffSize);
		trace.setName(format.name+"-"+format.fields.elementAt(fldid).name);
		trace.setPhysicalUnits("Time, ms", "Value");

		traces.put(key, trace);
		chart.addTrace(trace);
//		this.add(LayoutFactory.getInstance().createContextMenuLable(chart, trace));
	}
	
	
	public void messageEvent(DownlinkMessageEvent ev) {
		Message m = ev.getMessage();
		//if (m.acRec().state==Aircraft.NOTHING) return;
		int msgId=m.id();
		int msgC=m.msgClass();
		int ac=(msgC==0)?m.acRec().get_id():-1;
		if (!formats.containsKey(msgC*0x100000000l+msgId)) return;
		MessageFormat format=formats.get(msgC*0x100000000l+msgId);
		if (format.noClass || format.noId || format.noName || 
		format.noNameField>0 || format.noTypeField>0) return;
		
		//System.out.printf("msgc=%d,msgid=%d,n=%d\n",msgC,msgId,format.fields.size());
		long key=(((long)ac&0xFFl)<<16<<16)+(((long)msgId&0xFFl)<<16);
		Long[] n;
		long val;
		long key1;
		for (int i=0; i<format.fields.size(); i++)
		{
			key1=key+(i&0xFFl);
			if (msgSet.contains(key1))
			{
				n=m.getFields().get(i);
				val=MathFP.toLong(n[0]);
				ITrace2D trace=traces.get(key1);
				if (trace!=null)
				{
					trace.addPoint(m.time(), val);
					//System.out.println(msgId+":"+m.time()+":"+val);
				}
			}
		}
	}
}
